package va.radiomaria.gui;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Vector;
import va.radiomaria.audio.*;

/**
 * Stores the data which is displayed on the GUI, mainly MainWindow.java. Every 
 * change of the displayed data needs to be done on this model. The GUI will
 * automatically recognize the changes.
 */
public class DataModel extends Observable{
	private HashMap<LoggerInstance, String> consoleOutput;
	private Vector<Song> songsPlayed;
	private Vector<Vector<String>> information;
	private Vector<String> informationColumns;
	private static DataModel instance;
	private Mood currentMood;
	
	public synchronized static DataModel getInstance() 
    {
        if (instance == null) 
        {
            instance = new DataModel();
        }
        return instance;
    }
	
	private DataModel(){
		songsPlayed = new Vector<Song>();
		consoleOutput = new HashMap<LoggerInstance, String>();
		consoleOutput.put(LoggerInstance.ALL, "");
		consoleOutput.put(LoggerInstance.AUDIO, "");
		consoleOutput.put(LoggerInstance.RECOMMENDER, "");
		consoleOutput.put(LoggerInstance.MISC, "");
		consoleOutput.put(LoggerInstance.P2P, "");

		information = new Vector<Vector<String>>();
		currentMood = Mood.PARTY;
		
		informationColumns = new Vector<String>();
		informationColumns.add("Song title");
		informationColumns.add("Artist");
		informationColumns.add("Like counts");
		informationColumns.add("Streaming peer");
		
		addConsoleOutput("Welcome to Radio Maria!", LoggerInstance.ALL);
		
	}
	
	/**
	 * Adds the provided message to the MISC and ALL logger tabs. 
	 * @param loggingMessage
	 */
	public void addConsoleOutput(String loggingMessage)
	{
		addConsoleOutput(loggingMessage, LoggerInstance.MISC);
	}
	
	/**
	 * Adds the provides message to the specified and the ALL logger tabs.
	 * 
	 * @param loggingMessage
	 * @param instance
	 */
	public void addConsoleOutput(String loggingMessage, LoggerInstance instance)
	{
		Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String stringToAppend = " " + sdf.format(Calendar.getInstance().getTime()) + ": " + loggingMessage + "\n";
		consoleOutput.put(LoggerInstance.ALL, consoleOutput.get(LoggerInstance.ALL) + stringToAppend);
		if(instance != LoggerInstance.ALL && consoleOutput.containsKey(instance)) {
			consoleOutput.put(instance, consoleOutput.get(instance) + stringToAppend);
		}
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Returns all logger content stored by logger instance.
	 * @return
	 */
	public Map<LoggerInstance, String> getConsoleOutput(){
		return consoleOutput;
	}
	
	/**
	 * Add a row to the table of recently played songs
	 * @param info
	 */
	public void addSongsTableRow(String[] info){
		Vector<String> newSong = new Vector<String>();
		for(int i = 0; i < info.length; i++){
			newSong.add(info[i]);
		}
		information.add(newSong);
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Returns the list of all previously played songs
	 * @return
	 */
	public Vector<Song> getAllSongsPlayed(){
		return songsPlayed;
	}
	
	/**
	 * Add a song to the list of previously played songs
	 * @param song
	 */
	public void addSongToSongsPlayed(Song song) {
		songsPlayed.add(song);
	}
	
	/**
	 * clear the list of recently played songs
	 */
	public void removeSongsPlayed(){
		songsPlayed.removeAllElements();
	}
	
	/**
	 * Returns the song that is currently playing or paused
	 * @return
	 */
	public Song getCurrentSong()
	{
		if(songsPlayed.size()>0) {
			return songsPlayed.get(songsPlayed.size() -1);
		}
		else {
			return null;
		}
	}
	
	
	public Vector<String> getInformationColumns(){
		return informationColumns;
	}
	
	public Vector<Vector<String>> getInformationData(){
		return information;
	}

	/**
	 * Sets the current mood and updates the mood icons
	 * @param mood
	 */
	public void setCurrentMood(Mood mood){
		this.currentMood = mood;
		addConsoleOutput("Mood changed to: " + mood, LoggerInstance.MISC);
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Returns the currently active mood
	 * @return
	 */
	public Mood getCurrentMood(){
		return currentMood;
	}
	
}
